#include "noTree.h"

/*
 * @resume: construtor da classe noTree
 */
noTree::noTree() {
	this->nodeSons = NULL;
	this->conteudoSimplesNode = "";

}

/*
 * @resume: destrutor da classe noTree
 */
noTree::~noTree() {
	if (this->nodeSons == NULL) {
		delete this->nodeSons;
	}
}

/*
 * @resume: metodo para adicionar um filho na raiz
 * @param: string son
 * @return: noTree*
 */
noTree* noTree::addSon(string son) {
	noTree *node = new noTree();
	node->setNode(getNivelNode() + 1, son);
	node->setNodeFather(this);
	if (this->nodeSons == NULL) {
		this->nodeSons = new list<noTree*> ;
	}
	this->nodeSons->push_back(node);
	return (node);
}

/*
 * @resume: metodo para adicionar um filho (formado por uma lista) na raiz
 * @param: list<string> *son
 * @return: noTree*
 */
noTree* noTree::addSon(list<string> *son) {
	noTree *node = new noTree();
	node->setNode(getNivelNode() + 1, son);
	node->setNodeFather(this);
	if (this->nodeSons == NULL) {
		this->nodeSons = new list<noTree*> ;
	}
	this->nodeSons->push_back(node);
	return (node);
}

/*
 * @resume: metodo para adicionar uma subarvore na raiz
 * @param: noTree* subTreeNode
 * @return: noTree*
 */
noTree* noTree::addSubTree(noTree* subTreeNode) {
	subTreeNode->setNivelNode(getNivelNode() + 1);
	if (this->nodeSons == NULL) {
		this->nodeSons = new list<noTree*> ;
	}
	renewNivel(subTreeNode);
	this->nodeSons->push_back(subTreeNode);
	return (subTreeNode);
}

/*
 * @resume: metodo utilizado para percorrer um node da maneira reversa
 * @param: int& nivelDaBase, noTree* nodeAtual
 */
void noTree::percorreNodeReverse(int& nivelDaBase, noTree* nodeAtual) {
	list<noTree*>::reverse_iterator reverseIt;
	if (nodeAtual->hasSons()) {
		nivelDaBase++;
		for (reverseIt = nodeAtual->nodeSons->rbegin(); reverseIt
				!= nodeAtual->nodeSons->rend(); reverseIt++) {
			percorreNodeReverse(nivelDaBase, (*reverseIt));
		}
		nivelDaBase--;
		nodeAtual->setNivelNode(nivelDaBase);
	} else {
		nodeAtual->setNivelNode(nivelDaBase);
	}

}

/*
 * @resume: metodo utilizado renovar o nivel do node
 * @param: noTree* nodeBase
 */
void noTree::renewNivel(noTree* nodeBase) {
	int nivel = nodeBase->getNivelNode();
	percorreNodeReverse(nivel, nodeBase);
}

/*
 * @resume: metodo utilizado para setar o node propriamente dito
 * @param: int nivelNode, string conteudoSimplesNode
 */
void noTree::setNode(int nivelNode, string conteudoSimplesNode) {
	this->nivelNode = nivelNode;
	this->conteudoSimplesNode = conteudoSimplesNode;

}

/*
 * @resume: metodo utilizado para setar o node propriamente dito
 * @param: int nivelNode, list<string>*conteudoExpressaoNode
 */
void noTree::setNode(int nivelNode, list<string>*conteudoExpressaoNode) {
	if (conteudoExpressaoNode != NULL) {
		this->conteudoExpressaoNode = conteudoExpressaoNode;
	} else {
		this->conteudoExpressaoNode = NULL;
	}
	this->nivelNode = nivelNode;
}

/*
 * @resume: metodo utilizado para setar o pai do node propriamente dito
 * @param: noTree* nodeFather
 */
void noTree::setNodeFather(noTree* nodeFather) {
	this->nodeFather = nodeFather;
}

/*
 * @resume: metodo utilizado para setar o tipo do node
 * @param: Type typeNode
 */
void noTree::setTipoNode(Type typeNode) {
	this-> typeNode = typeNode;
}

/*
 * @resume: metodo utilizado para setar a linha do node
 * @param: int linhaNode
 */
void noTree::setLinhaNode(int linhaNode) {
	this->linhaNode = linhaNode;
}

/*
 * @resume: metodo utilizado para setar o nivel do node
 * @param: int nivelNode
 */
void noTree::setNivelNode(int nivelNode) {
	this->nivelNode = nivelNode;
}

/*
 * @resume: metodo utilizado para obeter o tipo do node
 * @return: Type typeNode
 */
Type noTree::getTipoNode() const {
	return (this->typeNode);
}

/*
 * @resume: metodo utilizado para obeter a linha do node
 * @return: int linhaNode
 */
int noTree::getLinhaNode() const {
	return (this->linhaNode);
}

/*
 * @resume: metodo utilizado para obeter o conteudo do node
 * @return: string conteudoSimplesNode
 */
string noTree::getConteudoSimplesNode() {
	return (this->conteudoSimplesNode);
}

/*
 * @resume: metodo utilizado para obeter o conteudo do node
 * @return: list<string> conteudoExpressaoNode
 */
list<string>* noTree::getConteudoExpressaoNode() {
	return (this->conteudoExpressaoNode);
}

/*
 * @resume: metodo utilizado para obeter o nivel do node
 * @return: int nivelNode
 */
int noTree::getNivelNode() const {
	return (this->nivelNode);
}

/*
 * @resume: metodo utilizado para verificar se um node possui filhos
 * @return: true: se possuir filhos
 * 			false: se nao
 */
bool noTree::hasSons() const {
	if (this->nodeSons == NULL) {
		return (false);
	}
	return (true);
}

/*
 * @resume: metodo utilizado para obeter o pai do node
 * @return: noTree* nodeFather
 */
noTree* noTree::getNodeFather() const {
	return (this->nodeFather);
}

/*
 * @resume: metodo utilizado para obeter os filhos do node
 * @return: list<noTree*> nodeSons
 */
list<noTree*> *noTree::getSons() const {
	return (this->nodeSons);
}

string noTree::getNameProcedureFunctionMepa() const {
	return (this->nameProcedureFunctionMepa);
}

void noTree::setNameProcedureFunctionMepa(string str) {
	this->nameProcedureFunctionMepa = str;
}

